package com.jacky.ocr_plugin.camera;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.jacky.util.OcrLogger;
import com.jacky.util.FilePathUtils;
import com.jacky.util.OcrOrientationEventListener;
import com.jacky.util.OcrRectManager;
import com.jacky.util.OcrUtil;
import com.jacky.util.OnOcrRectCallback;
import com.jacky.util.OnOcrRectErrorCallback;
import com.yunmai.cc.idcard.controler.OcrConstant;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;

/**
 * 使用不同的方式管理摄像头
 */
public class CustomOcrRectView2 extends FrameLayout {

    public CustomOcrRectView2(@NonNull Context context) {
        super(context);
        initView(context);
    }

    public CustomOcrRectView2(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    public CustomOcrRectView2(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }
    private OcrCameraPreviewView mCameraPreviewView;
    private Context mContext;
    public boolean isTakePictureFromPreview = false;
    private boolean isTakePictureWithRect = false;
    private OnOcrRectCallback mCallback;
    private OnOcrRectErrorCallback mErrorCallback;
    private OcrRectManager mRectManager;
    ///图片拍照的线程处理
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
    private HandlerThread mThread;
    private Handler mThreadHandler;
    private Runnable mThreadRun;
    //flutter定义参数，是否进行扫描、图片保存时是否旋转、扫描类型？-目前无用
    private boolean scanEnable = true;
    private boolean takePhotoRotated = true;
    private boolean portraitToLandscape = true;
    private int type = 0;
    ///是否进行ocr识别
    private boolean canOcrRect = false;

    private Rect overlayRec;
    private Rect mUsedRect;
    private String mOcrImgFilePath;
    private String mOcrHeadImgFilePath;
    private boolean mUseOrientation;
    private OcrOrientationEventListener mOrientationListener;
    private final Camera.PreviewCallback previewCallback = (data, camera) -> onPreviewDataRun(data);
    private int cameraGravity = Gravity.CENTER;
    //正在处理拍照的数据，防止多次处理数据返回
    private boolean mHandlingData = false;

    private void initView(Context context) {
        mContext = context;
        mCameraPreviewView = new OcrCameraPreviewView(context);
        addView(mCameraPreviewView);
        mOrientationListener = new OcrOrientationEventListener(context);
        mRectManager = OcrRectManager.get(context,mHandler);
        //mCameraPreviewView.setAutoFocusTime(800);//800毫秒，在flutter中使用时旋转手机会有卡主的感觉，一卡一卡的
        mCameraPreviewView.setPreviewCallback(previewCallback);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if(mOrientationListener != null)mOrientationListener.enable();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if(mOrientationListener != null)mOrientationListener.disable();
    }

    public void pause() {
        if (mCameraPreviewView != null) {
            stopDecoding();
            mCameraPreviewView.stopPreview();
            //直接释放，防止被占用挂了 不知道什么条件需要重新开相机
            mCameraPreviewView.releaseCamera();
        }
        if(mOrientationListener != null)mOrientationListener.disable();
    }

    public void setRecognizeRect(Rect recognizeRect) {
        //mUsedRect = getViewfinder(recognizeRect,portraitToLandscape);
        overlayRec = recognizeRect;
        updateRect();
    }

    public void resume() {
        if (mCameraPreviewView != null){
            checkCameraOpen();
            mCameraPreviewView.startPreview();
            startDecoding();
        }
        if(mOrientationListener != null)mOrientationListener.enable();
    }

    public void close() {
        if (mCameraPreviewView != null){
            mCameraPreviewView.stopPreview();
            mCameraPreviewView.releaseCamera();
        }
        mHandler.removeCallbacksAndMessages(null);
        if(mOrientationListener != null)mOrientationListener.disable();
        if(mThread != null)mThread.quit();
    }
    /**
     * 设置ocr识别图片的保存路径
     */
    public void setOcrImgFilePath(String filePath, String headPath) {
        mOcrImgFilePath = filePath;
        mOcrHeadImgFilePath = headPath;
    }

    /**
     * 拍照的图片，是否使用重力感应旋转图片
     */
    public void setUseImageOrientation(Boolean useOrientation){
        mUseOrientation = useOrientation != null && useOrientation;
    }

    /**
     * 切换摄像头
     */
    public void switchCamera(){
        if(mCameraPreviewView != null){
            mCameraPreviewView.switchCamera();
            startDecoding();
            updateRect();
        }
    }

    public void checkCameraOpen(){
        if(mCameraPreviewView != null){
            mCameraPreviewView.checkCameraOpen();
            startDecoding();
        }
    }

    public boolean setTorchFlash(boolean torchFlash) {
        if (mCameraPreviewView != null) {
            if (torchFlash) return  mCameraPreviewView.openFlashlight();
            else  return mCameraPreviewView.closeFlashlight();
        }
        return false;
    }

    public void stopDecoding(){
        setCanOcrRect(false);
    }

    public void startDecoding(){
        //需要参数支持扫描
        setCanOcrRect(scanEnable);
    }

    /**
     * 设置识别结果回调
     */
    public void setOcrRectCallback(OnOcrRectCallback callback) {
        this.mCallback = callback;
    }

    public void setOcrRectErrorCallback(OnOcrRectErrorCallback callback) {
        this.mErrorCallback = callback;
    }

    public void setParams(HashMap<String,Object> params){
        OcrLogger.d("setParams",params);
        if(params.containsKey("scanEnable")) {
            Boolean en = (Boolean) params.get("scanEnable");
            if(en != null) scanEnable = en;
            //切换是否扫描功能
            if(scanEnable) startDecoding();
            else stopDecoding();
        }
        if(params.containsKey("type")) {
            Integer t = (Integer) params.get("type");
            if(t != null) type = t;
        }
        if(params.containsKey("takePhotoRotated")) {
            Boolean t = (Boolean) params.get("takePhotoRotated");
            if(t != null) takePhotoRotated = t;
        }
        if(params.containsKey("ocrImgPath")) {
            String path = (String) params.get("ocrImgPath");
            if(path != null) mOcrImgFilePath = path;
        }
        if(params.containsKey("ocrHeadPath")) {
            String path = (String) params.get("ocrHeadPath");
            if(path != null) mOcrHeadImgFilePath = path;
        }
        //竖向转横向识别ocr：如手机竖向页面，转横向识别传true；pad是竖向识别传 false
        if(params.containsKey("portraitToLandscape")) {
            Boolean can = (Boolean) params.get("portraitToLandscape");
            if(can != null) {
                portraitToLandscape = can;
                updateRect();
            }
        }
        if(params.containsKey("androidUseImageOrientation")){
            setUseImageOrientation((Boolean) params.get("androidUseImageOrientation"));
        }
        if(params.containsKey("cameraGravity")){
            Integer gravity = (Integer) params.get("cameraGravity");
            if(gravity != null){
                switch (gravity){
                    case 1: updateGravity(Gravity.TOP);break;
                    case 2: updateGravity(Gravity.CENTER);break;
                    case 3: updateGravity(Gravity.BOTTOM);break;
                }
            }
        }else{
            updateGravity(cameraGravity);
        }
    }

    private void updateGravity(int gravity){
        if(mCameraPreviewView == null) return;
        mCameraPreviewView.setCameraGravity(gravity);
        cameraGravity = gravity;
    }

    private void updateRect(){
        mUsedRect = getViewfinder(overlayRec, portraitToLandscape);
        OcrLogger.d("mUsedRect",mUsedRect);
        mRectManager.setOcrRect(
                mCameraPreviewView.getPreviewWidth(),
                mCameraPreviewView.getPreviewHeight(),
                mUsedRect);

    }

    /**
     * 注意要放到子线程处理
     */
    private void handleData(byte[] data_p){
        if(mHandlingData){
            OcrLogger.d("handleData mHandlingData true");
            return;
        }
        if (data_p != null && data_p.length > 0) {
            if(isTakePictureFromPreview){
                onPreviewCallback(data_p);
                return;
            }
            if(isCanOcrRect()) {
                mRectManager.ocrRectData(data_p);
            }
        }
    }

    private boolean isCanOcrRect(){
        return canOcrRect;
    }

    private void setCanOcrRect(boolean can){
        canOcrRect = can;
    }

    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case OcrConstant.TAKE_PREVIEW_DATA_OK:
                    OcrLogger.d("------------------------------------data ok handle");
                    byte[] data_p = (byte[]) msg.obj;
                    if (data_p != null && data_p.length > 0){
                        onPreviewDataRun(data_p);
                    }
//                    if (data_p != null && data_p.length > 0) {
//                        if(isTakePictureFromPreview){
//                            onPreviewCallback(data_p);
//                            return;
//                        }
//                        if(isCanOcrRect()) {
//                            mRectManager.ocrRectData(data_p);
//                        }
//                    }
                    //每次聚焦，都会自动设置previewCallback，返回一帧数据，通知这里进行处理
                    break;
                case OcrConstant.RECOGN_OK:
                    //识别成功，进行处理数据
                    stopDecoding();
                    mHandler.removeMessages(OcrConstant.TAKE_PREVIEW_DATA_OK);
                    String imgFile = FilePathUtils.getFile(getContext(),mOcrImgFilePath, "ocr_img.jpg").getAbsolutePath();
                    String headFile = FilePathUtils.getFile(getContext(),mOcrHeadImgFilePath, "ocr_head.jpg").getAbsolutePath();
                    String info = mRectManager.getRectResult(imgFile,headFile);
                    if(info != null){
                        handleResultCallback(info, imgFile, headFile);
                    }
                    //让其可以继续识别
                    startDecoding();
                    break;
                case OcrConstant.RECOGN_EG_TIME_OUT:
                    error("3", "引擎过期，请尽快更新！");
                    break;
                case OcrConstant.RECOGN_EG_LICENSE:
                    error("3", "授权失败！");
                    break;
                case OcrConstant.RECOGN_EG_INIT_ERROR:
                    error("3", "引擎初始化失败！");
                    break;
                case OcrConstant.REPEAT_AUTOFOCUS:
                case OcrConstant.START_AUTOFOCUS:
                case OcrConstant.RECOGN_LINE_IN_RECT:
                    break;
                default:
                    if(mCameraPreviewView != null)mCameraPreviewView.startPreview();
                    OcrLogger.d("tag","flutter to android, ocr handler what "+msg.what);
                    break;
            }
        }

    };

    ///获取图片需要旋转角度
    private int getImageRotation(){
        //portraitToLandscape=true表示页面竖向但横向识别，false表示横向页面横向识别
        if(!mUseOrientation)return portraitToLandscape ? 90 : 0;
        if(mOrientationListener == null)return 0;
        mOrientationListener.setCameraFacingBack(mCameraPreviewView.isCameraFacingBack());
        return mOrientationListener.getRotation();
    }

//    private Rect getViewfinder(Rect rec){
//        return getViewfinder(rec,portraitToLandscape);
//    }


    ///将屏幕画面的rect区域，转为摄像头画面rect
    private Rect getViewfinder(Rect rec, boolean portraitToLandscape) {
        this.portraitToLandscape = portraitToLandscape;
        //摄像头显示的宽高
        int cameraW = mCameraPreviewView.getCameraWidth();
        int cameraH = mCameraPreviewView.getCameraHeight();
        //控件可用宽高
        int viewW = cameraW > 0 ? Math.min(cameraW,getWidth()) : getWidth();
        int viewH = cameraH > 0 ? Math.min(cameraH,getHeight()) : getHeight();
        if (rec == null) {
            rec = new Rect(0, 0, viewW, viewH);
        }
        overlayRec = rec;
        if(mCameraPreviewView == null)return rec;
        return OcrUtil.getViewRect(rec, mCameraPreviewView.getCameraAngle(), cameraGravity,
                mCameraPreviewView.getPreviewWidth(), mCameraPreviewView.getPreviewHeight(),
                cameraW, cameraH, getWidth(), getHeight());
//        int w = Math.max(getWidth(),getHeight());
//        int h = Math.min(getWidth(),getHeight());
//        int preW = mCameraPreviewView.getPreviewWidth();
//        int preH = mCameraPreviewView.getPreviewHeight();
//        float xs = (preW / (float) w);
//        float ys = (preH / (float) h);
//
//        int recH = rec.bottom - rec.top;
//        int recW = rec.right - rec.left;
//        int width;// = (int) ((rec.bottom - rec.top)*xs);
//        int height;// = (int) ((rec.right - rec.left)*ys);
//        Rect rect = new Rect();
//        int angle = mCameraPreviewView.getCameraAngle();
//        //angle = portraitToLandscape ? angle : 0;
//        //’代表度，0‘表示摄像头真实方向，90’代表预览方向 90度，w代表宽度，h代表高度
//        switch (angle){
//            case 90:
//                //0‘left = 90’top，0‘top=90’w-90‘right，90’w=0‘h
//                //使用xs 还是ys，有0’的left、top决定
//                rect.left = (int) (rec.top * xs);//(int) ((viewH() - rec.bottom) * xs);
//                rect.top = (int) ((viewW - rec.right) * ys);//(int) (rec.left * ys);
//                width = (int) (recH * xs);
//                height = (int) (recW * ys);
//                break;
//            case 180:
//                //0‘left = 180’w-180‘right，0‘top=180’h-180‘bottom，180’w=0‘w，180’h=0‘h
//                rect.left = (int) ((viewW - rec.right) * xs);//(int) ((viewW - rec.right) * xs);
//                rect.top = (int) ((viewH - rec.bottom) * ys);//(int) ((viewH() - rec.bottom) * ys);
//                width = (int) (recW * xs);
//                height = (int) (recH * ys);
//                break;
//            case 270:
//                //0‘left = 270’h-270’bottom，0‘top=270‘left，270’w=0‘h，270’h=0‘w
//                rect.left = (int) (((viewH - rec.bottom)) * xs);//(int) (rec.top* xs);
//                rect.top = (int) (rec.left * ys);//(int) ((viewW - rec.right) * ys);
//                width = (int) (recH * xs);
//                height = (int) (recW * ys);
//                break;
//            case 0:
//            default:
//                //0‘left = 360‘left,0‘top=360‘top,360’w=0‘w，360’h=0‘
//                rect.left = (int) (rec.left * xs);
//                rect.top = (int) (rec.top * ys);
//                width = (int) (recW * xs);
//                height = (int) (recH * ys);
//                break;
//        }
//        rect.right = rect.left + width;
//        rect.bottom = rect.top + height;
//        //因为摄像头画面居中了，导致摄像头预览区 跟getWidth控件区不一致，因此还有放大比例
//        float xss = cameraH <= 0 || w <= 0 ? 1f : Math.max(cameraH,cameraW) * 1f / Math.max(w,h);
//        float yss = cameraH <= 0 || w <= 0  ? 1f : Math.min(cameraH,cameraW) * 1f / Math.min(w,h);
//        //放大位置移动
//        Rect r = new Rect();
//        r.left = (int)(rect.left*xss);
//        r.top = (int)(rect.top*yss);
//        r.right = rect.right + (rect.left-r.left);
//        r.bottom = rect.bottom + (rect.top - r.top);
//        //getCameraAngle 90 camera w*h 1080 1920 get w*h 1080 2210 getDisplayMetrics w*h 1080 2132
//        // viewW w*h 1080 1920 pixel w*h 1080 2132 preview w*h 1920 1080 use w*h 2210 1080
//        // ratio xss*yss 0.8687783 1.0 ratio xs*ys 0.8687783 1.0 use rect Rect(509, 2 - 1409, 1080)
//        // use r Rect(442, 2 - 1476, 1080) overlay rect Rect(0, 586 - 1078, 1623)
////        DisplayMetrics dm = getResources().getDisplayMetrics();
////        OcrLogger.d(
////                "getCameraAngle",angle,
////                "camera w*h",cameraW,cameraH,
////                "get w*h",getWidth(),getHeight(),
////                "getDisplayMetrics w*h",dm.widthPixels,dm.heightPixels,
////                "viewW w*h",viewW,viewH,
////                "pixel w*h",dm.widthPixels,dm.heightPixels,
////                "preview w*h",preW,preH,
////                "use w*h",w,h,
////                "ratio xss*yss",xss,yss,
////                "ratio xs*ys",xs,ys,
////                "use rect",rect,
////                "use r",r,
////                "overlay rect",rec);
//        return r;
    }

    ///处理识别结果，
    // 头像照格式：{"Name":{"value":""}, "Sex":{"value":""},"Folk":{"value":""},
    // "Birt":{"value":""},"Addr":{"value":""},"Num":{"value":""} }
    //国徽照格式：{"Issue":{"value":""},"Valid":{"value":""},}
    private void handleResultCallback(String result, String imgPath, String headPath) {
        try {
            JSONObject json = new JSONObject(result);
            HashMap<String, Object> map = new HashMap<>();
            for (Iterator<String> iterator = json.keys(); iterator.hasNext(); ) {
                String key = iterator.next();
                String value = getValue(json, key);
                map.put(key.toLowerCase(), value);
            }
            map.put("imgPath", imgPath);
            map.put("headPath", headPath);
            if (mCallback != null) {
                mCallback.callback(map);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * 拍照返回数据
     * @param imgPath 图片保存路径
     */
    private void handleResultCallback(String imgPath){
        HashMap<String, Object> map = new HashMap<>();
        map.put("imgPath", imgPath);
        if (mCallback != null) {
            mCallback.callback(map);
        }
    }

    private String getValue(JSONObject json, String key) throws JSONException {
        if (json != null && json.has(key)) {
            JSONObject value = json.optJSONObject(key);
            return value != null ? (String) value.opt("value") : null;
        }
        return null;
    }


    private void error(String code, String message) {
        OcrLogger.d("ocrRectView", "error code " + code + " message " + message);
        if (mErrorCallback != null)
            mErrorCallback.callback(code, message);
    }
    /**
     * 摄像头 拍照
     */
    public void takePhotoCamera(){
        if (mCameraPreviewView != null) {
//            mCameraPreviewView.takePicture(this::onPictureTaken);
            //交由聚焦后处理保存图片
            isTakePictureFromPreview = true;
            //mCameraPreviewView.autoFocus(null);
        }
    }

    /**
     * 摄像头 拍照图片 根据rect进行截取
     */
    public void takePhotoCameraWithRect(){
        if (mCameraPreviewView != null) {
            isTakePictureFromPreview = true;
            isTakePictureWithRect = true;
        }
    }

    /**
     * 处理camera.takePicture拍照后的数据，部分手机如oppo会对其旋转处理
     * 导致统一的旋转处理后，总是有部分手机图片出现旋转问题
     */
    private void onPictureTaken(byte[] data, Camera camera) {
        mThread = getThread();
        if(mThreadRun != null) mThreadHandler.removeCallbacks(mThreadRun);
        //线程处理数据
        mThreadRun = new TakePictureRun(data);
        mThreadHandler.post(mThreadRun);
        //拍一次照片，开启再次预览
        mMainHandler.postDelayed(()->mCameraPreviewView.startPreview(),350);
    }

    /**
     * 线程处理  数据，防止影响主线程，造成flutter的摄像头画面卡顿
     */
    private void onPreviewDataRun(byte[] data){
        if(mRectManager.isNeedUpdatePreviewSize()){
            mRectManager.setOcrRect(mCameraPreviewView.getPreviewWidth(),mCameraPreviewView.getPreviewHeight(),null);
        }
        mThread = getThread();
        //线程处理数据
        mThreadRun = () -> handleData(data);
        mThreadHandler.post(mThreadRun);
    }

    /**
     * 获取线程
     */
    private HandlerThread getThread(){
        if(mThread == null || !mThread.isAlive()){
            mThread = new HandlerThread("savePicture");
            OcrLogger.d("mThread HandlerThread");
            mThread.setUncaughtExceptionHandler((Thread t, Throwable e) -> {
                OcrLogger.d("ocrRectView2 thread savePicture exception");
                OcrLogger.d(e);
            });
            mThread.start();
            mThreadHandler  = new Handler(mThread.getLooper());
        }
        if(mThreadRun != null) mThreadHandler.removeCallbacks(mThreadRun);
        return mThread;
    }

    private void onPreviewCallback(byte[] data){
        mThread = getThread();
        //线程处理数据
        mCameraPreviewView.stopPreview();
        stopDecoding();
        File file = FilePathUtils.getFile(getContext(), mOcrImgFilePath, "ocr_img.jpg");
        int rotation = getImageRotation();
        OcrLogger.d("preview getImageRotation",rotation,"androidUseImageOrientation"
                ,mUseOrientation,"portraitToLandscape",portraitToLandscape);
        mHandlingData = true;
        mThreadRun = new PreviewDataRunnable(
                data,
                mCameraPreviewView.getPreviewWidth(),
                mCameraPreviewView.getPreviewHeight(),
                file,
                rotation,
                isTakePictureWithRect ? mUsedRect : null,
                () -> mMainHandler.postDelayed(() -> {
                    if (mCameraPreviewView != null) {
                        mCameraPreviewView.startPreview();
                        startDecoding();
                    }
                    isTakePictureFromPreview = false;
                    isTakePictureWithRect = false;
                    mHandlingData = false;
                    handleResultCallback(file.getAbsolutePath());
                }, 350));//new TakePictureRun(data);
        mThreadHandler.post(mThreadRun);
    }



    /**
     * 处理预览数据的图片保存
     */
    public static class PreviewDataRunnable implements  Runnable{
        private final byte[] data;
        private final int previewWidth;
        private final int previewHeight;
        private final File saveFile;
        private final Runnable complete;
        private final int rotation;
        private final int imageFormat;
        private final Rect useRect;

        public PreviewDataRunnable(
                byte[] data,
                int previewWidth,
                int previewHeight,
                File saveFile,
                int rotation,
                int imageFormat,
                Rect useRect,
                Runnable complete) {
            this.data = data;
            this.previewWidth = previewWidth;
            this.previewHeight = previewHeight;
            this.saveFile = saveFile;
            this.complete = complete;
            this.rotation = rotation;
            this.imageFormat = imageFormat;
            this.useRect = useRect;
        }

        public PreviewDataRunnable(
                byte[] data,
                int previewWidth,
                int previewHeight,
                File saveFile,
                int rotation,
                Rect useRect,
                Runnable complete) {
            this(data,previewWidth,previewHeight,saveFile,rotation,ImageFormat.NV21,useRect,complete);
        }

        @Override
        public void run() {
            Bitmap bm = getBitmap();
            if(bm == null){
                if(complete != null) complete.run();
                return;
            }
            try {
                saveBitmap(bm);
            }catch (Exception e){
                OcrLogger.d(e);
            }
            if(complete != null) complete.run();
        }

        private Bitmap getBitmap(){
            try {
                if(data.length == 0) {
                    OcrLogger.d("PreviewDataRunnable data is empty data.length == 0");
                    return null;
                }
                byte[] image;
                if(ImageFormat.NV21 == imageFormat){
                    YuvImage yuvImage = new YuvImage(data, imageFormat, previewWidth, previewHeight, null);
                    ByteArrayOutputStream bao = new ByteArrayOutputStream();
                    yuvImage.compressToJpeg(new Rect(0,0,previewWidth,previewHeight), 100, bao);
                    //图片转bitmap
                    image = bao.toByteArray();
                }else {
                    image = data;
                }
                BitmapFactory.Options options = new BitmapFactory.Options();//防止oom
                options.inPreferredConfig = Bitmap.Config.RGB_565;
                return BitmapFactory.decodeByteArray(image, 0, image.length, options);
            }catch (Exception e){
                e.printStackTrace();
            }
            return null;
        }

        private void saveBitmap(Bitmap bm){
            //旋转
            int width = bm.getWidth(), height = bm.getHeight();
            int max = Math.max(width, height);
            float scale = max > 1500 ? (1500f / max) : 0;
            Bitmap bm2 = null;
            //rotation 90 scale 0.78125 useRect Rect(516, 0 - 1484, 1080) 1920 1080
            OcrLogger.d("rotation",rotation,"scale",scale,"useRect",useRect,width,height);
            if (rotation != 0 || scale != 0 || useRect != null) {
                Matrix m = new Matrix();
                if(rotation != 0) m.setRotate(rotation, 0, 0);
                if(scale != 0) m.preScale(scale, scale);
                try {
                    if(useRect != null && useRect.left + useRect.width() <= width && useRect.top + useRect.height() <= height){
                        bm2 = Bitmap.createBitmap(bm, useRect.left, useRect.top, useRect.width(), useRect.height(), m, true);
                    }else {
                        bm2 = Bitmap.createBitmap(bm, 0, 0, width, height, m, true);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
                //bm.recycle();//提前释放，导致保存文件为空
                bm = bm2;
            }
            //保存图片
            if(saveFile.exists())saveFile.delete();
            FilePathUtils.saveBitmap(saveFile, bm, Bitmap.CompressFormat.JPEG, 80);
            if(bm != null) bm.recycle();
            if(bm2 != null && !bm2.isRecycled())bm2.recycle();
        }

    }



    /**
     * camera.tackPicture的数据保存，有问题前置摄像头保存的图片是
     */
    public class TakePictureRun implements Runnable{
        private final byte[] data;
        TakePictureRun(byte[] data){
            this.data = data;
        }

        @Override
        public void run() {
            File file = FilePathUtils.getFile(getContext(),mOcrImgFilePath, "ocr_img.jpg");
            String imgFile = file.getAbsolutePath();
            //OcrLogger.d("imgFile",imgFile);
            if(!portraitToLandscape){
                FilePathUtils.savePicture(data,imgFile);
            } else{
                int ro = getImageRotation();
                //图片
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inTempStorage = new byte[100 * 1024];
                options.inPreferredConfig = Bitmap.Config.RGB_565;
                options.inPurgeable = true;
                Bitmap bm = BitmapFactory.decodeByteArray(data,0,data.length,options);
                //缩放比例
                int width = bm.getWidth(),height = bm.getHeight();
                int max = Math.max(width,height);
                float scale = max > 1500 ? (1500f/max) : 0;
                OcrLogger.d("rotation",ro,"scale",scale,"width",width,"height",height);
                //旋转
                Bitmap bm2 = null;
                if(ro != 0 || scale != 0){
                    Matrix m = new Matrix();
                    if(ro != 0) m.setRotate(ro,0,0);
                    if(scale != 0) m.preScale(scale,scale);
                    bm2 = Bitmap.createBitmap(bm,0,0,width,height, m, true);
                    //bm.recycle();//bm 回收后，bm2也回收了
                    bm = bm2;
                }
                FilePathUtils.saveBitmapLimitSize(file, bm, 80);
                bm.recycle();
                if(bm2 != null && !bm2.isRecycled()){
                    bm2.recycle();
                }
            }
            mMainHandler.post(()->handleResultCallback(imgFile));
        }
    }
}
